package com.coocaa.ops.api.v1.home.service.internal;

import com.coocaa.ops.api.base.model.BaseQueryModel;
import com.coocaa.ops.api.base.third.dmp.IDmpService;
import com.coocaa.ops.api.common.model.HeaderModel;
import com.coocaa.ops.api.v1.home.cache.HomepageCacheImpl;
import com.coocaa.ops.api.v1.home.cache.IHomepageCache;
import com.coocaa.ops.api.v1.home.cache.IModuleCache;
import com.coocaa.ops.api.v1.home.model.query.HomeQueryModel;
import com.coocaa.ops.common.core.biz.dmp.entity.DmpRegistryRlsInfoEntity;
import com.coocaa.ops.common.core.biz.homepage.entity.HomeModuleContentConfigInfo;
import com.coocaa.ops.common.core.biz.module.entity.ModuleInfoEntity;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * @author tangminghong
 * @date 2020-09-02
 */
@Service
public class DmpHomeAndModuleService {

    @Autowired
    private IHomepageCache homepageCache;

    @Autowired
    private IModuleCache moduleCache;

    @Autowired
    private IDmpService dmpService;

    /**
     *
     * @param normalModuleList
     * @param homeQueryModel
     * @return
     */
    public List<HomeModuleContentConfigInfo> handleModuleDmp(List<HomeModuleContentConfigInfo> normalModuleList, HomeQueryModel homeQueryModel) {
        List<HomeModuleContentConfigInfo> dmpModuleList = homepageCache.getDmpModuleList(homeQueryModel);
        Map<Integer, HomeModuleContentConfigInfo> dmpModuleSeqMap = matchAndGetDmpModulesBySeq(dmpModuleList, homeQueryModel.getHeader());
        return getFinalModuleList(normalModuleList, dmpModuleSeqMap);
    }

    public void handleTabDmp(List<? extends ModuleInfoEntity> moduleList, BaseQueryModel queryModel) {
        List<DmpRegistryRlsInfoEntity> dmpInfoList = getTabAllDmpInfo(moduleList, queryModel);
        if (CollectionUtils.isEmpty(dmpInfoList)) { return; }
        Map<Integer, Map<Integer, DmpRegistryRlsInfoEntity>> dmpInfoMap = matchAndGetTabDmpByModuleId(dmpInfoList, queryModel);
        handleFinalModuleTabDmp(moduleList, dmpInfoMap);

    }

    /*********************模块dmp相关私有方法**************************/

    /**
     * 匹配并返回人群匹配的模块
     * @param dmpModuleList
     * @return key为seq
     */
    private Map<Integer, HomeModuleContentConfigInfo> matchAndGetDmpModulesBySeq(List<HomeModuleContentConfigInfo> dmpModuleList, HeaderModel header) {
        if (CollectionUtils.isEmpty(dmpModuleList)) {
            return Collections.emptyMap();
        }
        Set<Integer> policyIds = getModuleAllPolicyId(dmpModuleList);
        Set<Integer> crowdIds = getMatchedCrowdIdFromDmp(policyIds, header);

        LinkedHashMap<Integer, HomeModuleContentConfigInfo> result = new LinkedHashMap<>();
        for (HomeModuleContentConfigInfo module : dmpModuleList) {
            DmpRegistryRlsInfoEntity dmpInfo = module.getDmpRegistryInfo();
            if (dmpInfo != null) {
                Integer seq = dmpInfo.getSubContainerSeq();
                module.setSeq(seq);
                if (result.get(seq) == null && matched(dmpInfo, crowdIds)) {
                    result.put(seq, module);
                } else if (result.get(seq) != null && matched(dmpInfo, crowdIds)){
                    HomeModuleContentConfigInfo oldModule = result.get(seq);
                    Integer contentSeq = dmpInfo.getSubContainerContentSeq();
                    Integer oldContentSeq = oldModule.getDmpRegistryInfo().getSubContainerContentSeq();
                    if (contentSeq < oldContentSeq) {
                        result.put(seq, module);
                    }

                }
            }

        }
        return result;
    }


    private Set<Integer> getModuleAllPolicyId(List<HomeModuleContentConfigInfo> moduleList) {
        if (CollectionUtils.isEmpty(moduleList)) {
            return Collections.emptySet();
        }
        Set<Integer> result = new HashSet<>(moduleList.size());
        for (HomeModuleContentConfigInfo module : moduleList) {
            DmpRegistryRlsInfoEntity dmpInfo = module.getDmpRegistryInfo();
            if (dmpInfo != null) {
                result.add(dmpInfo.getDmpPolicyId());
            }
        }
        return result;
    }

    private List<HomeModuleContentConfigInfo> getFinalModuleList(List<HomeModuleContentConfigInfo> normalModuleList, Map<Integer, HomeModuleContentConfigInfo> dmpModuleMap) {

        List<HomeModuleContentConfigInfo> finalModuleList = normalModuleList == null ? new ArrayList<>(0) : new ArrayList<>(normalModuleList);
        dmpModuleMap = dmpModuleMap == null ? Collections.emptyMap() : dmpModuleMap;

        /**
         * 逻辑：首先将普通模块列表中匹配dmp的位置替换为dmp匹配的模块，然后将剩余的dmp匹配的模块添加到末尾，最后再根据seq排序
         */
        ListIterator<HomeModuleContentConfigInfo> i = finalModuleList.listIterator();
        while (i.hasNext()) {
            HomeModuleContentConfigInfo module = i.next();
            Integer seq = module.getSeq();
            if (dmpModuleMap.containsKey(seq)) {
                i.set(dmpModuleMap.get(seq));
                dmpModuleMap.remove(seq);
            }
        }

        finalModuleList.addAll(dmpModuleMap.values());

        finalModuleList.sort(Comparator.comparing(HomeModuleContentConfigInfo::getSeq));


        return finalModuleList;
    }


    /*********************版面dmp相关私有方法**************************/

    private List<DmpRegistryRlsInfoEntity> getTabAllDmpInfo(List<? extends ModuleInfoEntity> moduleList, BaseQueryModel queryModel) {
        if (CollectionUtils.isEmpty(moduleList)) {
            return Collections.emptyList();
        }
        List<DmpRegistryRlsInfoEntity> result = new ArrayList<>(2 * moduleList.size());
        for (ModuleInfoEntity module : moduleList) {
            if (Objects.equals(module.getHasDmp(), 1)) {
                List<DmpRegistryRlsInfoEntity> dmpInfoList = moduleCache.getModuleTabDmpInfo(module.getId(), module.getCurrentVersion(), queryModel.getPolicyCategory());
                if (CollectionUtils.isNotEmpty(dmpInfoList)) {
                    result.addAll(dmpInfoList);
                }
            }
        }
        return result;
    }

    /**
     *
     * @param dmpList
     * @param queryModel
     * @return 第一层key为模块id，第二层key为1或2（1为上边版面，2为下边版本）
     */
    private Map<Integer, Map<Integer,DmpRegistryRlsInfoEntity>> matchAndGetTabDmpByModuleId(List<DmpRegistryRlsInfoEntity> dmpList, BaseQueryModel queryModel) {

        if (CollectionUtils.isEmpty(dmpList)) {
            return Collections.emptyMap();
        }

        Set<Integer> policyIds = getTabAllPolicyId(dmpList);
        Set<Integer> crowdIds = getMatchedCrowdIdFromDmp(policyIds, queryModel.getHeader());

        LinkedHashMap<Integer, Map<Integer, DmpRegistryRlsInfoEntity>> result = new LinkedHashMap<>();
        for (DmpRegistryRlsInfoEntity dmpInfo : dmpList) {
            Integer moduleId = dmpInfo.getParentContainerId();
            Integer seq = dmpInfo.getSubContainerSeq();

            if (matched(dmpInfo, crowdIds)) {
                if (Objects.equals(seq,1) || Objects.equals(seq,2)) {
                    Map<Integer, DmpRegistryRlsInfoEntity> seqDmpMap = result.computeIfAbsent(moduleId, HashMap::new);
                    DmpRegistryRlsInfoEntity oldDmpInfo = seqDmpMap.get(seq);
                    if (oldDmpInfo == null) {
                        seqDmpMap.put(seq, dmpInfo);
                    } else {
                        Integer oldContentSeq = oldDmpInfo.getSubContainerContentSeq();
                        Integer contentSeq = dmpInfo.getSubContainerContentSeq();
                        if (contentSeq < oldContentSeq) {
                            seqDmpMap.put(seq, dmpInfo);
                        }
                    }
                }
            }
        }

        return result;
    }


    private Set<Integer> getTabAllPolicyId(List<DmpRegistryRlsInfoEntity> dmpInfoList) {
        if (CollectionUtils.isEmpty(dmpInfoList)) {
            return Collections.emptySet();
        }

        Set<Integer> result = new HashSet<>(dmpInfoList.size());
        for (DmpRegistryRlsInfoEntity dmpInfo : dmpInfoList) {
            result.add(dmpInfo.getDmpPolicyId());
        }
        return result;
    }

    private void handleFinalModuleTabDmp(List<? extends ModuleInfoEntity> moduleList, Map<Integer,Map<Integer,DmpRegistryRlsInfoEntity>> moduleIdTabSeqDmpInfoMap) {
        if (CollectionUtils.isEmpty(moduleList) || moduleIdTabSeqDmpInfoMap == null) {return;}

        for (ModuleInfoEntity module : moduleList) {
            if (Objects.equals(module.getHasDmp(),1)) {
                Map<Integer,DmpRegistryRlsInfoEntity> moduleTabDmpMap = moduleIdTabSeqDmpInfoMap.get(module.getId());
                if (moduleTabDmpMap == null) {
                    continue;
                }
                DmpRegistryRlsInfoEntity topTabDmp = moduleTabDmpMap.get(1);
                DmpRegistryRlsInfoEntity bottomTabDmp = moduleTabDmpMap.get(2);

                if (topTabDmp != null) { module.setTopTabId(topTabDmp.getSubContainerId());}
                if (bottomTabDmp != null) { module.setBottomTabId(bottomTabDmp.getSubContainerId());}
            }
        }
    }

    /*********************dmp相关公共私有方法**************************/

    private Set<Integer> getMatchedCrowdIdFromDmp(Set<Integer> policyIds, HeaderModel header) {
        return dmpService.getMatchedCrowdIdsFromDmp(policyIds, header);
    }

    private boolean matched(DmpRegistryRlsInfoEntity dmpInfo, Set<Integer> crowdIds) {
        if (CollectionUtils.isEmpty(crowdIds)) {
            return false;
        }
        return crowdIds.contains(dmpInfo.getDmpCrowdId());
    }


}
